#ifndef __SDRV_COMMON_H__
#define __SDRV_COMMON_H__

#include <linux/printk.h>
#include <linux/string.h>

#ifndef NULL
#define NULL (0)
#endif

//======================================================
/** __FILE__ 中路径的去除
 *  在使用的时候会带上路径，在代码中打印的时候往往不需要这个路径，只需要一个函数名
 *  在这里通过调用kernel中的库函数、自定义宏、内联函数等三种方式去除__FILE__中的路径。
 */

/**
 * @brief  __FILE__NAME()
 * @note   通过调用 linux/string.h 中的 strrchr()函数来去除 __FILE__ 中的路径。
 */
#define __FILE__NAME(str) (strrchr(str,'/')?(strrchr(str,'/')+1):str) // 内核下 linux/string.h 中有这个strrchr函数

 /**
 * @brief  STRRCHR()
 * @note   STRRCHR() 是一个宏，用于查找字符串中最后出现的字符.
 *         需要注意的是,仅在内核下去除文件路径使用，其他情况并未详细测试，不保证完全没有问题
 *         这里是通过宏实现的，所以编译链接的时候都不会检查参数类型，会有一定的风险
 * @param [in] x: The string to be searched
 * @param [in] c: The character to search for
 * @param [out]
 * @retval 
 */
#define STRRCHR(x, c)                                 \
        ({                                            \
            char *s = x; char *p = NULL;              \
            do{                                       \
                if(*s == (char)c){p = s;}             \
            } while(*s++);                            \
            (p);                                      \
        })
#define __FILE__NAME1(str) (STRRCHR(str, '/')?(STRRCHR(str,'/')+1):str)

/**
 * @brief  sstrrchr()
 * @note   sstrrchr() 是一个内联函数，在调用的时候会直接展开。定义成内联函数的话可以方便的放在.h文件中
 *         注意，是否会展开取决于编译的时候的优化选项
 * @param [in] s: The string to be searched
 * @param [in] c: The character to search for
 * @param [out]
 * @retval 
 */
static inline char *sstrrchr(const char *s, int c)
{
	const char *last = NULL;
	do {
		if (*s == (char)c)
			last = s;
	} while (*s++);
	return (char *)last;
}
#define __FILE__NAME2(str) (sstrrchr(str,'/')?(sstrrchr(str,'/')+1):str)

#define PRT(fmt, args...)  \
        do                 \
        {                  \
            printk("[INFO][%s:%d][%s]"fmt, __FILE__NAME(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)

#define PRT1(fmt, args...)  \
        do                 \
        {                  \
            printk("[INFO][%s:%d][%s]"fmt, __FILE__NAME1(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)

#define PRT2(fmt, args...)  \
        do                 \
        {                  \
            printk("[INFO][%s:%d][%s]"fmt, __FILE__NAME2(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)

#define PRTE(fmt, args...)  \
        do                 \
        {                  \
            printk("[ERROR][%s:%d][%s]"fmt, __FILE__NAME(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)

#define PRTE1(fmt, args...)  \
        do                 \
        {                  \
            printk("[ERROR][%s:%d][%s]"fmt, __FILE__NAME1(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)

#define PRTE2(fmt, args...)  \
        do                 \
        {                  \
            printk("[ERROR][%s:%d][%s]"fmt, __FILE__NAME2(__FILE__), __LINE__, __FUNCTION__, ##args);\
        } while(0)
#endif /* __SDRV_COMMON_H__ */
